Skip to content

[ty] Improve keyword argument narrowing for nested dictionaries#24010

Merged
ibraheemdev merged 1 commit intomainfrom
ibraheem/dict-unpack-narrowing
Mar 20, 2026
Merged

[ty] Improve keyword argument narrowing for nested dictionaries#24010
ibraheemdev merged 1 commit intomainfrom
ibraheem/dict-unpack-narrowing

Conversation

@ibraheemdev
Copy link
Member

Fixes a bug in #23436 where nested dictionary literals are not tracked, e.g.,

def f(a: int, b: str): ...

x = {"inner": {"a": 1, "b": "a"}}
f(**x["inner"])

This is unlikely to have an ecosystem impact, but seems worth doing nonetheless.

@ibraheemdev ibraheemdev added the ty Multi-file analysis & type inference label Mar 17, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 17, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 85.29%. The percentage of expected errors that received a diagnostic held steady at 78.13%. The number of fully passing files held steady at 64/132.

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 17, 2026

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 17, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-await 0 40 0
invalid-return-type 0 1 0
Total 0 41 0

Full report with detailed diff (timing results)

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change adds false negatives for direct assignments to nested keys:

def f(*, b: int): ...

x: dict[str, dict[str, int]] = {"a": {"b": 1}}
x["a"]["b"] = 1

# This should be an error: x has no top-level key "b".
f(**x)

This is correctly an error on main, but a false negative with this PR.

@ibraheemdev
Copy link
Member Author

@carljm that example seems to error correctly on this PR?

➜  sandbox git:(ibraheem/dict-unpack-narrowing) ✗ cargo run --bin ty --manifest-path ~/dev/astral/ruff/Cargo.toml check main.py
error[invalid-argument-type]: Argument to function `f` is incorrect
  --> main.py:23:3
   |
22 | # This should be an error: x has no top-level key "b".
23 | f(**x)
   |   ^^^ Expected `int`, found `dict[str, int]`
   |
info: Function defined here
  --> main.py:17:5
   |
15 | #         self.mylist = [None, None, None]
16 |
17 | def f(*, b: int): ...
   |     ^    ------ Parameter declared here
18 |
19 | x: dict[str, dict[str, int]] = {"a": {"b": 1}}
   |
info: rule `invalid-argument-type` is enabled by default

Found 1 diagnostic

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, sorry! I'm sure I tested that... not sure what I did wrong. Maybe I had an earlier branch checked out by accident. Never mind!

@ibraheemdev ibraheemdev merged commit b6f3b5c into main Mar 20, 2026
53 checks passed
@ibraheemdev ibraheemdev deleted the ibraheem/dict-unpack-narrowing branch March 20, 2026 11:14
carljm added a commit that referenced this pull request Mar 25, 2026
* main:
  [`flake8-bandit`] Check tuple arguments for partial paths in `S607` (#24080)
  [ty] Update Salsa (#24081)
  Update Rust toolchain to 1.94 and MSRV to 1.92 (#24076)
  [ty] Move ruffen-docs formatting config to a `ruff.toml` config file (#24074)
  [ty] `reveal_type` diagnostics in unreachable code (#24070)
  [ty] Improve keyword argument narrowing for nested dictionaries (#24010)
  [ty] Preserve blank lines between comments and imports in add-import action (#24066)
  [ty] Add diagnostic hint for invalid assignments involving invariant generics (#24032)
  Clarify `extend-ignore` and `extend-select` settings documentation (#24064)
  [ty] Batch changes to watched paths (#24045)
  replace deprecated `std::f64::EPSILON` with `f64::EPSILON` (#24067)
  [ty] Fix untracked reads in Salsa queries that can lead to backdating panics (#24051)
  [ty] Unions/intersections of gradual types should be assignable to `Never` (#24056)
  Fix incorrect path for ty_python_semantic in fuzzer (#24052)
  Bump 0.15.7 (#24049)
  [ty] ecosystem-analyzer: Fail on newly panicking projects (#24043)
  Don't show noqa hover for non-Python documents (#24040)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants